﻿''' <summary>
''' builds a where clause from a collection of CriterionMetadata object
''' </summary>
''' <remarks></remarks>
Public Class ReportCriteriaProcessor
    Implements IReportCriteriaProcessor

    Private Const DEFAULT_WHERE_CLAUSE As String = " WHERE 1=1 AND "
    Private Const STR_AND As String = " AND "

    Property report() As ReportMatadata Implements IReportCriteriaProcessor.report

    ''' <summary>
    ''' collection of objects that will be passed as parameters to the sql being build
    ''' </summary>
    Public Property sqlParameterValues As List(Of Object) = _
            New List(Of Object) Implements IReportCriteriaProcessor.sqlParameterValues

    Private _parametersAsString As List(Of String)
    Private _parametersSql As List(Of String)
    Private _parametersCounter As Integer = 0

    Public Sub resetParameters() Implements IReportCriteriaProcessor.resetParameters
        Me._sqlParameterValues = New List(Of Object)
        Me._parametersAsString = Nothing
        Me._parametersSql = Nothing
        Me._parametersCounter = 0
    End Sub

    Property parameterCounter As Integer Implements IReportCriteriaProcessor.parameterCounter
        Get
            Return _parametersCounter
        End Get
        Set(ByVal value As Integer)
            _parametersCounter = value
        End Set
    End Property

    ''' <summary>
    ''' Nothing valued parameters are skipped.  
    ''' If parameter is not nothing, the sql is built and added to
    ''' an sql string, and the <b>value</b> is added to a list of objects.
    ''' This list will be used to execute the parametrized sql.
    ''' </summary>
    ''' <param name="c">ICriterionMetadata</param>
    ''' <remarks>
    ''' </remarks>
    Protected Sub addToCriteria(ByVal c As ICriterionMetadata)

        c.criterionBuilder.buildCriterion(c, Me)

        If String.IsNullOrEmpty(c.criterionBuilder.SqlCriteria) = False Then
            Me._parametersSql.Add(c.criterionBuilder.SqlCriteria)
            Me._parametersAsString.Add(c.criterionBuilder.HumanCrieria)
        End If

    End Sub

    ''' <summary>
    ''' Returns the sql where clause of the criteria collection, based on values in those criteria
    ''' </summary>
    ''' <returns>SQL String</returns>
    ''' <remarks></remarks>
    Public Function getCriteriaSQL() As String _
                        Implements IReportCriteriaProcessor.getCriteriaSQL

        If _parametersSql Is Nothing Then
            Me.processCriteria()
        End If

        If _parametersSql.Count > 0 Then
            Return DEFAULT_WHERE_CLAUSE & String.Join(STR_AND, _parametersSql)
        Else
            Return String.Empty
        End If

    End Function

    Private Sub processCriteria()

        Me._parametersSql = New List(Of String)
        Me._parametersAsString = New List(Of String)

        For Each c As ICriterionMetadata In Me.report.Criteria
            If Not c.isTransient Then
                Call addToCriteria(c)
            End If
        Next
    End Sub

    Public Function getCriteriaAsString() As String _
            Implements IReportCriteriaProcessor.getCriteriaAsString

        If _parametersAsString Is Nothing Then
            Me.processCriteria()
        End If

        Return String.Join(",", _parametersAsString)

    End Function
End Class
